//Written in the D Programming Language
/*
 * Copyright (c) 2008 OpenGLUtils
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'OpenGLUtils' nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
module testapps.TestDisplayLists;

import testapps.TestApp;

import openglutils.GL;
import openglutils.GLU;
import openglutils.SDL;
import openglutils.GLDisplayList;
import openglutils.GLTexture;
import openglutils.TextureLoader;

import tango.stdc.stringz;

void main(char[][] args)
{
	auto test = new TestDisplayLists();
	test.createGLWindow("Test Display Lists", 800, 600, 32, false);
	test.initGL();
	test.loadGLTextures();
	test.buildLists();
	test.run();
	delete test;
}

public class TestDisplayLists: TestApp
{
	GLTexture2D texture;
	GLDisplayList box;
	GLDisplayList top;

	GLfloat xrot = 0.0f;
	GLfloat yrot = 0.0f;

	GLfloat boxcol[5][3] = [
		[1.0f, 0.0f, 0.0f],
		[1.0f, 0.5f, 0.0f],
		[1.0f, 1.0f, 0.0f],
		[0.0f, 1.0f, 0.0f],
		[0.0f, 1.0f, 1.0f]
	];

	GLfloat topcol[5][3] = [
		[0.5f, 0.0f, 0.0f],
		[0.5f, 0.25f, 0.0f],
		[0.5f, 0.5f, 0.0f],
		[0.0f, 0.5f, 0.0f],
		[0.0f, 0.5f, 0.5f]
	];
	
	void buildLists()
	{
		box = new GLDisplayList();
		box.compileList(
		{
			glBegin(GL_QUADS);
			{
				glNormal3f(0.0f, -1.0f, 0.0f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(-1.0f, -1.0f, -1.0f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(1.0f, -1.0f, -1.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(1.0f, -1.0f, 1.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(-1.0f, -1.0f, 1.0f);

				glNormal3f(0.0f, 0.0f, 1.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(-1.0f, -1.0f, 1.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(1.0f, -1.0f, 1.0f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(1.0f, 1.0f, 1.0f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(-1.0f, 1.0f, 1.0f);

				glNormal3f(0.0f, 0.0f, -1.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(-1.0f, -1.0f, -1.0f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(-1.0f, 1.0f, -1.0f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(1.0f, 1.0f, -1.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(1.0f, -1.0f, -1.0f);

				glNormal3f(1.0f, 0.0f, 0.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(1.0f, -1.0f, -1.0f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(1.0f, 1.0f, -1.0f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(1.0f, 1.0f, 1.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(1.0f, -1.0f, 1.0f);

				glNormal3f(-1.0f, 0.0f, 0.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(-1.0f, -1.0f, -1.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(-1.0f, -1.0f, 1.0f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(-1.0f, 1.0f, 1.0f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(-1.0f, 1.0f, -1.0f);
			}
			glEnd();
		});
		
		top = new GLDisplayList();
		top.compileList(
		{
			glBegin(GL_QUADS);
			{
				glNormal3f(0.0f, 1.0f, 0.0f);
				glTexCoord2f(0.0f, 1.0f);
				glVertex3f(-1.0f, 1.0f, -1.0f);
				glTexCoord2f(0.0f, 0.0f);
				glVertex3f(-1.0f, 1.0f, 1.0f);
				glTexCoord2f(1.0f, 0.0f);
				glVertex3f(1.0f, 1.0f, 1.0f);
				glTexCoord2f(1.0f, 1.0f);
				glVertex3f(1.0f, 1.0f, -1.0f);
			}
			glEnd();
		});
	}

	void loadGLTextures()
	{
		texture = TextureLoader.loadTexture2D("testapps/data/Cube.bmp");
	}

	void keyPressed(int key)
	{
		switch(key)
		{
			case SDLK_RIGHT:
				yrot += 0.2f;
				break;
			case SDLK_LEFT:
				yrot -= 0.2f;
				break;
			case SDLK_DOWN:
				xrot += 0.2f;
				break;
			case SDLK_UP:
				xrot -= 0.2f;
				break;
			default:
				break;
		}
	}

	void keyReleased(int key)
	{
		if(key == SDLK_ESCAPE)
		{
			running = false;
		}
	}

	void drawGLScene()
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		texture.bind();
		
		GLuint xloop;
		GLuint yloop;
		
		for(yloop = 1; yloop < 6; yloop++)
		{
			for(xloop = 0; xloop < yloop; xloop++)
			{
				glLoadIdentity();
				glTranslatef(1.4f + (xloop * 2.8f) - (yloop * 1.4f), ((6.0f - yloop) * 2.4f) - 7.0f, -20.0f);
				glRotatef(45.0f - (2.0f * yloop) + xrot, 1.0f, 0.0f, 0.0f);
				glRotatef(45.0f + yrot, 0.0f, 1.0f, 0.0f);

				glColor3fv(boxcol[yloop - 1].ptr);
				box.call();

				glColor3fv(topcol[yloop - 1].ptr);
				top.call();
			}
		}
	}

	~this()
	{
		delete box;
		delete top;
		delete texture;
	}
}
